import org.jsecurity.authc.AccountException
import org.jsecurity.authc.IncorrectCredentialsException
import org.jsecurity.authc.UnknownAccountException
import org.jsecurity.authc.SimpleAccount
import org.jsecurity.authc.credential.CredentialsMatcher
import org.jsecurity.authc.credential.Sha256CredentialsMatcher

class AuthRealm {
	
	CredentialsMatcher credentialMatcher
	
	static authTokenClass = org.jsecurity.authc.UsernamePasswordToken
	
	def authenticate(authToken) {
		
		//log "Attempting to authenticate ${authToken.username} in Auth realm..."
		def username = authToken.username
		
		// Null username is invalid
		if (username == null) {
			// log "Null username is invalid"
			throw new AccountException('Null usernames are not allowed by this realm.')
		}
		
		// Get the user with the given username. If the user is not
		// found, then they don't have an account and we throw an
		// exception.
		def accountDB = Account.findByUsername(username)
		//log "Found user '${accountDB?.username}' in DB"
		if (!accountDB) {
			//log "No account found for user [${username}]"
			throw new UnknownAccountException("No account found for user [${username}]")
		}
		
		// Now check the user's password against the hashed value stored
		// in the database.
		def simpleAccount = new SimpleAccount(username, accountDB.password, "AuthRealm")
		
		credentialMatcher = new Sha256CredentialsMatcher();
		credentialMatcher.storedCredentialsHexEncoded = false
		if (!credentialMatcher.doCredentialsMatch(authToken, simpleAccount)) {
			//log 'Invalid password (Auth realm)'
			throw new IncorrectCredentialsException("Invalid password for user '${username}'")
		}
		
		return username
	}
	
	/*
	 * Mock behaviour for now. Authorization/Entitlement not implemented
	 */
	def hasRole(principal, roleName) {
		def user = Account.findByUsername(principal)
		return user.role = Role.USER
	}
	
	/*
	 * Mock behaviour for now. Authorization/Entitlement not implemented
	 */
	def isPermitted(principal, requiredPermission) {
		// no permission level authentication implemented yet
		return true
	}
}
